from public.jygt_coder_loger import get_logger 
logger = get_logger(__name__)

from flask import Blueprint, request, redirect, url_for, send_file
import os
import tarfile
import tempfile
from mako.lookup import TemplateLookup
from process.get_task_desc import getTaskDesc
from process.generate_code import generateCode

bp = Blueprint('index', __name__)

def get_template_lookup():
    current_dir = os.path.dirname(__file__)
    return TemplateLookup(
        directories=[
            os.path.join(current_dir, 'template'),
            os.path.join(current_dir, '../../dat/', 'template')
        ]
    )

@bp.route("/", methods=['GET'])
def index():
    logger.info("Accessing index page")
    
    lookup = get_template_lookup()
    template = lookup.get_template('index.html.mako')

    # 定义要传递给模板的变量
    title = "JYGT-CODER"
    heading = "欢迎使用 JYGT-CODER ！"
    message = "使用pymysql,sqlalchemy,flask,graphql构建！"
    
    # 获取任何可能的错误或成功消息
    error = request.args.get('error')
    success = request.args.get('success')

    # 获取目标目录和数据库名参数
    tar_root_dir = request.args.get('tar_root_dir')
    db_database = request.args.get('db_database')
    
    return template.render(
        title=title,
        heading=heading,
        message=message,
        error=error,
        success=success,
        tar_root_dir=tar_root_dir,
        db_database=db_database
    )

@bp.route("/generate", methods=['POST'])
def generate():
    logger.info("Received form submission")
    try:
        # 获取表单数据，使用与cmdline.py相同的参数名和默认值
        db_host = request.form.get('db_host', 'www.nationaiot.com')
        db_port = request.form.get('db_port', '23060')
        db_database = request.form.get('db_database','db_enger')
        db_user = request.form.get('db_user', 'root')
        db_password = request.form.get('db_password', 'root1234')
        
        api_host = request.form.get('api_host', 'localhost')
        api_port = request.form.get('api_port', '5005')
        api_path = request.form.get('api_path', '/graphql')
        
        tar_root_dir = request.form.get('tar_root_dir',"d:\\dist\\")
        tar_ver = request.form.get('tar_ver', '1.0.0')

        # 验证必需的字段
        if not all([db_database, tar_root_dir]):
            logger.error("Missing required fields")
            return redirect(url_for('index.index', error='数据库名和目标目录是必需的'))

        # 验证端口号
        try:
            db_port = int(db_port)
            api_port = int(api_port)
            if db_port < 1 or db_port > 65535 or api_port < 1 or api_port > 65535:
                raise ValueError("Invalid port number")
        except ValueError:
            logger.error(f"Invalid port numbers: db_port={db_port}, api_port={api_port}")
            return redirect(url_for('index.index', error='端口号必须是1-65535之间的数字'))

        # 确保目标目录存在
        try:
            os.makedirs(tar_root_dir, exist_ok=True)
        except Exception as e:
            logger.error(f"Failed to create target directory: {str(e)}")
            return redirect(url_for('index.index', error=f'无法创建目标目录：{str(e)}'))

        # 创建参数字典
        params = {
            'db_host': db_host,
            'db_port': db_port,
            'db_database': db_database,
            'db_user': db_user,
            'db_password': db_password,
            'api_host': api_host,
            'api_port': api_port,
            'api_path': api_path,
            'tar_root_dir': tar_root_dir,
            'tar_ver': tar_ver
        }

        logger.info(f"Starting code generation with params: {params}")

        # 获取任务描述
        taskInfo = getTaskDesc(**params)

        logger.info(f"\n{'#'*10} JYGT-CODER 准备处理下面任务：{'#'*10}\n{taskInfo}")
        
        # 初始化任务
        logger.info(f"\n1. 加载数据库，并初始化目标工程目录{taskInfo.getTargetProjectInfo().getRootDir()}")
        taskInfo.init()
        logger.info(f"\t << 加载表数量： {len(taskInfo.getDBInfo().getInfo())}")
        logger.info(f"\t << 初始化目标工程目录 {taskInfo.getTargetProjectInfo().getRootDir()}")
        
        # 生成代码
        res = generateCode(taskInfo)

        logger.info(f"代码生成 { '成功' if generateCode(taskInfo) else '失败'}")
        if res:
            # 将 tar_root_dir 添加到成功消息的查询参数中
            return redirect(url_for('index.index', 
                success=f'代码已成功生成到目录：{tar_root_dir}', 
                tar_root_dir=tar_root_dir,
                db_database=db_database))
        else:
            return redirect(url_for('index.index', error=f'代码生成失败'))
    except Exception as e:
        logger.error(f"Unexpected error during code generation: {str(e)}", exc_info=True)
        return redirect(url_for('index.index', error=f'代码生成失败：{str(e)}'))

@bp.route("/download", methods=['GET'])
def download():
    logger.info("Received download request")
    try:
        # 获取目标目录和数据库名参数
        tar_root_dir = request.args.get('tar_root_dir')
        db_database = request.args.get('db_database')
        
        if not tar_root_dir or not db_database:
            logger.error("Download failed: Missing required parameters")
            return redirect(url_for('index.index', error='下载失败：缺少必要参数'))
        
        # 构建实际的目标目录路径（数据库名命名的目录）
        target_dir = os.path.join(tar_root_dir, db_database)
        if not os.path.exists(target_dir):
            logger.error(f"Download failed: Directory not found - {target_dir}")
            return redirect(url_for('index.index', error='下载失败：目录不存在'))
        
        # 创建临时文件用于存储压缩包
        with tempfile.NamedTemporaryFile(suffix='.tar.gz', delete=False) as temp_file:
            temp_path = temp_file.name
            
        # 创建tar.gz文件
        with tarfile.open(temp_path, "w:gz") as tar:
            # 使用数据库名作为压缩包内的根目录名
            tar.add(target_dir, arcname=db_database)
        
        logger.info(f"Created archive at {temp_path} for directory {target_dir}")
        
        # 发送文件给客户端下载
        return send_file(
            temp_path,
            as_attachment=True,
            download_name=f"{db_database}.tar.gz",
            mimetype='application/gzip'
        )
    except Exception as e:
        logger.error(f"Download failed: {str(e)}", exc_info=True)
        return redirect(url_for('index.index', error=f'下载失败：{str(e)}'))